🐳 Docker 备份系统
🐳 Docker 备份系统
一键备份 · 数据库安全导出 · 双网盘上传 · GPG 加密 · Telegram 远程管理
📖 项目概述
自动备份 VPS 上所有运行中的 Docker 容器(含 docker-compose 项目),内建数据库智能检测与安全导出,支持上传到 OneDrive + Google Drive 双网盘,并可通过 Telegram Bot 进行远程管理。
⚠️ 核心规则:仅备份 Running 状态的容器
脚本通过docker ps扫描当前处于 Running 状态的容器。已停止 (Exited) 或暂停 (Paused) 的容器不会被备份。如需备份某个已停止的容器,请先docker start <容器>启动它。
🗄️ 数据库智能导出
自动检测 MySQL / MariaDB / PostgreSQL / MongoDB 容器,使用mysqldump/pg_dumpall/mongodump执行一致性安全导出。导出失败时自动降级为卷打包,不中断整体备份流程。
🎯 核心能力
| 能力 | 说明 |
|---|---|
| 🐳 全容器备份 | 所有 Running 容器的 inspect JSON + 卷数据 + 运行参数 |
| 🧩 Compose 支持 | 自动识别 docker-compose 项目,打包完整的 docker-compose.yml + 目录 |
| 🗄️ 数据库安全导出 | MySQL / MariaDB / PostgreSQL / MongoDB 专用导出,保证数据一致性 |
| � GPG 加密 | 可选 AES256 对称加密,备份文件上传前自动加密 |
| ☁️ 双网盘上传 | OneDrive + Google Drive 自动上传,远程保留策略 |
| 🤖 Telegram Bot | 远程查看状态、手动触发备份,实时回显执行进度 |
| 🔄 完整还原 | 一键恢复所有容器(含 compose 项目 + 数据库 dump + 卷数据) |
| 🌐 多网络支持 | host / bridge / 自定义 bridge / compose 网络全兼容 |
| ⚙️ 参数全保留 | 还原时完整保留 --privileged / --shm-size / --dns / --security-opt / --cap-drop / --init / HEALTHCHECK / labels / workdir 等 |
📄 项目文件
| 📄 文件 | 🎯 用途 |
|---|---|
bf.sh | 主备份脚本,支持 cron 定时或手动执行 |
db_dump.sh | 数据库自动检测 + 专用安全导出模块 |
restore.sh | 一键恢复脚本(容器 + Compose + 数据库 dump) |
tg_bot.py | Telegram Bot,远程查看状态 / 触发备份 |
tg_bot.service | Bot 的 systemd 服务文件 |
install_bot.sh | Bot 一键部署脚本 |
⚙️ 一、环境要求
| 项目 | 要求 |
|---|---|
| 🖥️ 操作系统 | Ubuntu 20.04+ / Debian 11+ / CentOS 7+ |
| 🐳 Docker | 已安装并正常运行(docker ps 可执行) |
| 🔑 权限 | root |
| 🔧 Git | 已安装 |
| ☁️ 网盘 (可选) | rclone 已配置 onedrive 和 gdrive remote |
🚀 二、部署步骤
📥 步骤 1 — 拉取项目
cd /rootgit clone https://github.com/Agff45/vps_docker-bf.git bfcd /root/bfchmod +x *.sh📦 步骤 2 — 安装系统依赖
apt update && apt install -y jq tar gzip curl🔐 可选:安装 GPG 加密支持
Terminal window apt install -y gnupg
☁️ 步骤 3 — 配置 rclone 网盘 (可选)
🚨 重要:rclone remote 名必须固定为
onedrive和gdrive,脚本通过名称识别网盘。
📂 点击展开 rclone 配置步骤
# 安装 rclonecurl https://rclone.org/install.sh | bash
# 交互式配置(remote 名必须填写 onedrive 和 gdrive)rclone config配置过程中按提示操作:
- 输入
n新建 remote - 名称输入
onedrive - 类型选择
onedrive(OneDrive)或drive(Google Drive) - 按提示完成 OAuth 授权
# 验证配置是否成功rclone lsd onedrive:rclone lsd gdrive:💡 不想用网盘? 跳过此步骤即可。备份会保存在本地
VPS_Backups/目录,网盘上传步骤会显示失败,不影响本地备份。
🤖 步骤 4 — 配置 Telegram (可选)
两个配置项的区别:
TG_BOT_TOKEN/BOT_TOKEN— Telegram 机器人的 Token,由 @BotFather 发放,格式123456:ABC-DEF1234gh...TG_CHAT_ID/ALLOWED_CHAT_ID— 你个人账户的数字 ID,由 @userinfobot 查询,格式123456789两者缺一不可:Token 让脚本操控机器人,Chat ID 确保只有你能发命令。
📝 编辑 bf.sh
nano /root/bf/bf.sh找到配置区域,修改以下三行:
TG_BOT_TOKEN="你的BotToken"TG_CHAT_ID="你的ChatID"TG_ENABLED=true # 不需要通知就改为 false📝 编辑 tg_bot.py
nano /root/bf/tg_bot.py修改第 16-17 行:
BOT_TOKEN = "你的BotToken"ALLOWED_CHAT_ID = 你的ChatID⚠️ 如果不想用 Telegram 通知和 Bot,在
bf.sh中把TG_ENABLED设为false,并且不要执行步骤 9。
🗄️ 步骤 5 — 数据库备份配置 (可选)
bf.sh 默认已启用数据库自动检测。如需关闭:
# bf.sh 配置区域DB_DUMP_ENABLED=false # 设为 false 关闭数据库专用导出支持的数据库类型
| 数据库 | 检测方式 | 导出命令 | 导出文件 |
|---|---|---|---|
| MySQL | 镜像名含 mysql | mysqldump --all-databases --single-transaction --routines --triggers --events | 容器名_mysqldump_all.sql.gz |
| MariaDB | 镜像名含 mariadb | mysqldump --all-databases --single-transaction | 容器名_mysqldump_all.sql.gz |
| PostgreSQL | 镜像名含 postgres / postgis | pg_dumpall | 容器名_pgdumpall.sql.gz |
| MongoDB | 镜像名含 mongo | mongodump --archive | 容器名_mongodump.archive.gz |
凭证自动提取机制
| 数据库 | 读取的环境变量 |
|---|---|
| MySQL | MYSQL_ROOT_PASSWORD |
| MariaDB | MARIADB_ROOT_PASSWORD |
| PostgreSQL | POSTGRES_USER + POSTGRES_PASSWORD |
| MongoDB | MONGO_INITDB_ROOT_USERNAME + MONGO_INITDB_ROOT_PASSWORD |
自动降级策略
如果专用导出失败(容器内缺少客户端工具 / 密码错误 / 无认证 MongoDB 等),脚本自动回退为 卷数据 tar 打包,不中断备份。
🔐 步骤 6 — GPG 加密备份 (可选)
启用后备份文件在上传前使用 AES256 对称加密,生成 .tar.gz.gpg 文件。
安装 GPG:
apt install -y gnupg配置 bf.sh:
ENCRYPT_ENABLED=true # 开启加密ENCRYPT_PASSPHRASE="你的加密密码" # 设置密码(⚠️ 必须设置,空密码会跳过加密)恢复加密备份:
./restore.sh backup.tar.gz.gpg 你的加密密码🧪 步骤 7 — 测试备份
/root/bf/bf.sh✅ 正常输出流程:
依赖检查→容器扫描→数据库检测→数据导出→打包完成→网盘上传结果
预期输出示例:
[Sun May 3 01:07:37 CST 2026] 🚀 开始 Docker 容器备份...🔍 检查依赖... ✅ 所有依赖就绪🐳 正在扫描 Docker 容器...📋 发现 23 个运行中的容器
🕵️ ==== 数据库自动检测 ==== 🔍 检测到数据库: [mysql_main] 类型=mysql 🔍 检测到数据库: [postgres_main] 类型=postgres 📊 共检测到 2 个数据库容器
🩺 对数据库容器 [mysql_main] (mysql) 执行专用导出... ✅ [mysql_main] 导出成功: mysql_main_mysqldump_all.sql.gz (876K) 🩺 对数据库容器 [postgres_main] (postgres) 执行专用导出... ✅ [postgres_main] 导出成功: postgres_main_pgdumpall.sql.gz (20K)
✅ 数据库专用导出完成: 2/2 个成功
📦 打包备份目录... ✅ 打包完成: docker_backup_20260503_010737.tar.gz (2.5M)🎉 所有任务完成.⏰ 步骤 8 — 设置定时任务
(crontab -l 2>/dev/null; echo "0 3 * * * /root/bf/bf.sh >> /var/log/docker_backup.log 2>&1") | crontab -📅 默认每天 凌晨 3 点 自动执行,可自行修改 cron 表达式。
📂 Crontab 常用时间参考
| 时间 | 表达式 |
|---|---|
| 每天凌晨 2 点 | 0 2 * * * |
| 每天凌晨 3 点 | 0 3 * * * |
| 每 6 小时 | 0 */6 * * * |
| 每周日凌晨 3 点 | 0 3 * * 0 |
🔌 步骤 9 — 部署 Telegram Bot (可选)
/root/bf/install_bot.sh脚本自动完成:
- 创建 Python 虚拟环境
- 安装
python-telegram-bot依赖 - 配置 systemd 服务并设为开机自启
# Bot 管理命令systemctl status tg_bot # 查看运行状态systemctl restart tg_bot # 重启 Botsystemctl stop tg_bot # 停止 Botjournalctl -u tg_bot -f # 实时查看日志✔️ 步骤 10 — 验证部署
| ✅ 检查项 | 📟 命令 |
|---|---|
| 手动备份 | /root/bf/bf.sh |
| 查看备份文件 | ls -lh /root/bf/VPS_Backups/ |
| Bot 状态 | systemctl status tg_bot |
| 定时任务 | crontab -l |
🔄 三、恢复备份
基本用法
cd /root/bf
# 恢复未加密备份./restore.sh VPS_Backups/docker_backup_YYYYMMDD_HHMMSS.tar.gz
# 恢复加密备份./restore.sh VPS_Backups/docker_backup_YYYYMMDD_HHMMSS.tar.gz.gpg 你的加密密码恢复流程 (4 步自动执行)
┌─────────────────────────────────────────────────┐│ 1️⃣ 还原 docker-compose 项目 ││ · 解压 compose 项目目录 ││ · docker compose up -d 启动 ││ · 已运行的项目自动跳过 │├─────────────────────────────────────────────────┤│ 2️⃣ 还原普通 Docker 容器 ││ · 恢复卷数据 (tar) ││ · 还原 SSH 端口映射 / 环境变量 / 网络 / 重启策略 ││ · 还原 tmpfs / read_only / cap / init / DNS ││ · 还原 HEALTHCHECK / labels / workdir ││ · 缺失的自定义网络自动创建 │├─────────────────────────────────────────────────┤│ 3️⃣ 还原 /home/docker 下的文件 │├─────────────────────────────────────────────────┤│ 4️⃣ 还原数据库 dump ││ · 等待数据库就绪(健康检查轮询,最多 60s) ││ · zcat dump.gz → mysql / psql / mongorestore │└─────────────────────────────────────────────────┘恢复时完整保留的 docker run 参数
| 参数 | 来源 | 备注 |
|---|---|---|
--name | 容器名 | 原始名称 |
-p | HostConfig.PortBindings | TCP/UDP 协议完整保留;host 网络自动跳过 |
-e | Config.Env | 含特殊字符(!@#$% / 引号 / 换行) |
-v | Mounts | bind mount + volume 均支持 |
--network | HostConfig.NetworkMode | 缺失网络自动 docker network create |
--restart | HostConfig.RestartPolicy | 含 on-failure:N 重试次数 |
--tmpfs | HostConfig.Tmpfs | 保留 size 参数 |
--read-only | HostConfig.ReadonlyRootfs | |
--cap-drop / --cap-add | HostConfig.CapDrop / CapAdd | |
--init | HostConfig.Init | |
--privileged | HostConfig.Privileged | |
--shm-size | HostConfig.ShmSize | 字节精确还原 |
--dns | HostConfig.Dns | 支持多个 |
--security-opt | HostConfig.SecurityOpt | 支持多个 |
--health-cmd / --health-interval / --health-timeout / --health-retries | Config.Healthcheck | 纳秒自动转秒 |
--label | Config.Labels | 自动跳过 com.docker.* 内部标签 |
--workdir | Config.WorkingDir | |
IMAGE [CMD...] | Config.Image + Config.Cmd | 保留原始启动命令 |
🛡️ 已运行的容器及 Compose 项目会自动跳过,不会重复创建。
📋 四、完整配置参考
bf.sh 全部配置项
# ================= 配置区域 =================# --- 本地设置 ---BACKUP_DIR="/root/bf/VPS_Backups" # 本地备份存放目录LOCAL_KEEP_COUNT=1 # 本地保留最近 N 份
# --- 网盘 1: OneDrive ---REMOTE1_NAME="onedrive" # rclone remote 名称REMOTE1_DIR="VPS_Backups/Docker" # 远程目标目录
# --- 网盘 2: Google Drive ---REMOTE2_NAME="gdrive" # rclone remote 名称REMOTE2_DIR="VPS_Backups/Docker" # 远程目标目录REMOTE_KEEP_COUNT=4 # 网盘各保留最近 N 份
# --- Telegram ---TG_BOT_TOKEN="你的BotToken" # Bot TokenTG_CHAT_ID="你的ChatID" # 你的 Chat IDTG_ENABLED=true # 是否启用通知
# --- 数据库专用导出 ---DB_DUMP_ENABLED=true # 是否启用数据库自动检测
# --- GPG 加密 ---ENCRYPT_ENABLED=false # 是否启用加密ENCRYPT_PASSPHRASE="" # 加密密码(留空不加密)tg_bot.py 配置项
BOT_TOKEN = "你的BotToken"ALLOWED_CHAT_ID = 你的ChatID💬 五、Telegram Bot 命令
| 🎮 命令 | 🧩 功能 | 说明 |
|---|---|---|
/start | 欢迎消息 | 显示可用命令列表 |
/status | 查看备份状态 | 最近一次备份的完整统计(容器数 / DB 导出数 / 文件大小 / 上传状态) |
/run | 手动触发备份 | 实时回显 bf.sh 执行进度 |
/help | 帮助信息 | 命令说明 |
📁 六、VPS 目录结构
/root/bf/├── 📜 bf.sh # 主备份脚本├── 📜 db_dump.sh # 数据库检测 + 导出模块├── 📜 restore.sh # 一键恢复脚本├── 📜 tg_bot.py # Telegram Bot 脚本├── 📜 tg_bot.service # systemd 服务文件├── 📜 install_bot.sh # Bot 一键部署脚本├── 📜 README.md # 本文档├── 📜 .gitignore # Git 忽略规则├── 📁 venv/ # Python 虚拟环境 (install_bot.sh 创建)├── 📄 backup_status.json # 最近一次备份状态 JSON└── 📁 VPS_Backups/ # 本地备份存放目录 └── 📦 docker_backup_*.tar.gz # 备份文件(本地保留最新 N 份)🗑️ 七、完全卸载
🤖 卸载 Telegram Bot
systemctl stop tg_botsystemctl disable tg_botrm -f /etc/systemd/system/tg_bot.servicesystemctl daemon-reload⏰ 删除定时任务
crontab -l | grep -v '/root/bf/bf.sh' | crontab -📂 删除项目文件
rm -rf /root/bf📋 删除备份日志
rm -f /var/log/docker_backup.log⚡ 一键卸载(复制整段到终端执行):
systemctl stop tg_bot 2>/dev/nullsystemctl disable tg_bot 2>/dev/nullrm -f /etc/systemd/system/tg_bot.servicesystemctl daemon-reloadcrontab -l 2>/dev/null | grep -v '/root/bf/bf.sh' | crontab -rm -rf /root/bfrm -f /var/log/docker_backup.logecho "✅ 卸载完成"🔄 八、更新项目
cd /root/bfgit pullchmod +x *.sh❓ 九、常见问题
🌐 Q: git clone 失败(国内服务器)?
# 方式一:使用镜像站git clone https://ghproxy.com/https://github.com/Agff45/vps_docker-bf.git bf
# 方式二:使用代理git config --global http.proxy http://127.0.0.1:端口git config --global https.proxy http://127.0.0.1:端口git clone https://github.com/Agff45/vps_docker-bf.git bf📝 Q: 脚本报 syntax error?
sed -i 's/\r$//' /root/bf/*.sh原因:Windows 换行符
\r\n与 Linux 不兼容。
📦 Q: 备份时提示缺少依赖?
apt install -y jq tar gzip curl rclone☁️ Q: 网盘上传失败?
确认 rclone remote 已正确配置:
rclone lsd onedrive:rclone lsd gdrive:💡 如果不想用网盘,上传失败不影响本地备份。
🤖 Q: Bot 启动失败?
journalctl -u tg_bot -n 50 # 查看错误日志systemctl restart tg_bot # 重试启动常见原因:Token 错误、网络不通、Python 依赖未安装。
🐳 Q: 恢复时容器启动失败?
一般为镜像未拉取或网络不存在,手动处理后重试:
docker pull <镜像名>docker network create <网络名> # 如果 restore.sh 未能自动创建./restore.sh <备份文件>🗄️ Q: 数据库导出失败怎么办?
备份日志中会显示 ⚠️ [容器名] 导出失败,将回退到卷打包方式 以及 🔍 错误详情。
常见原因和解决方案:
| 症状 | 原因 | 解决 |
|---|---|---|
mysqldump: command not found | 精简镜像不含客户端 | 回退卷打包,或换用完整镜像 |
| 密码为空导出失败 | 环境变量缺失 | 回退卷打包 |
| pg_dumpall 报权限错误 | 非超级用户 | 回退卷打包 |
| MongoDB 无认证导出失败 | 不支持空密码场景 | 回退卷打包 |
🔐 Q: GPG 加密提示 "未设置密码,跳过加密"?
ENCRYPT_ENABLED=true 但没有设置 ENCRYPT_PASSPHRASE。设置密码即可:
nano /root/bf/bf.sh# 修改: ENCRYPT_PASSPHRASE="你的密码"🌐 Q: 自定义网络容器恢复后网络不存在?
restore.sh 已自动处理此场景 — 恢复时会检测网络是否存在,不存在则自动 docker network create。
如果还是失败,手动创建即可:
docker network create <网络名>Made with ❤️ for VPS & Docker users


